package com.dbflow5.runtime;

import com.dbflow5.DemoApp;
import com.dbflow5.ImmediateTransactionManager;
import com.dbflow5.TestDatabase;
import com.dbflow5.config.DBFlowDatabase;
import com.dbflow5.config.FlowManager;
import com.dbflow5.database.OhosSQLiteOpenHelper;
import com.dbflow5.models.SimpleModel_Table;
import com.dbflow5.models.SimpleTestModels.SimpleModel;
import com.dbflow5.query.SQLite;
import com.dbflow5.structure.ChangeAction;

import decc.testkit.runner.HarmonyJUnitClassRunner;
import ohos.aafwk.ability.delegation.AbilityDelegatorRegistry;
import ohos.app.Context;
import ohos.utils.Pair;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;


@RunWith(HarmonyJUnitClassRunner.class)
public class DirectNotifierTest {
    private final Context context;

    public DirectNotifierTest() {
        context = AbilityDelegatorRegistry.getAbilityDelegator().getAppContext();
    }

    @Before
    public void setupTest() {
        FlowManager.init(context, builder -> {
            builder.database(TestDatabase.class, builder12 -> {
                builder12.transactionManagerCreator(ImmediateTransactionManager::new);
                return null;
            }, OhosSQLiteOpenHelper.createHelperCreator(DemoApp.context));
            return null;
        });
    }

    @Test
    public void validateCanNotifyDirect() {
        FlowManager.databaseForTable(SimpleModel.class, db -> {
            DirectModelNotifier.OnModelStateChangedListener<SimpleModel> modelChange = new DirectModelNotifier.ModelChangedListener<SimpleModel>() {
                @Override
                public void onModelChanged(SimpleModel model, ChangeAction action) {
                    switch (model.name){
                        case "INSERT":
                            assert action == ChangeAction.INSERT;
                            break;
                        case "UPDATE":
                            assert action == ChangeAction.UPDATE;
                            break;
                        case "CHANGE":
                            assert action == ChangeAction.CHANGE;
                            break;
                        case "DELETE":
                            assert action == ChangeAction.DELETE;
                            break;
                        default:
                            break;
                    }
                }

                @Override
                public void onTableChanged(Class<?> table, ChangeAction action) {

                }
            };
            DirectModelNotifier.get().registerForModelStateChanges(SimpleModel.class, modelChange);

            FlowManager.getModelAdapter(SimpleModel.class).insert(new SimpleModel("INSERT"), db);
            FlowManager.getModelAdapter(SimpleModel.class).update(new SimpleModel("UPDATE"), db);
            FlowManager.getModelAdapter(SimpleModel.class).save(new SimpleModel("CHANGE"), db);
            FlowManager.getModelAdapter(SimpleModel.class).delete(new SimpleModel("DELETE"), db);
            return null;
        });
    }

    @Test
    public void validateCanNotifyWrapperClasses(){
        DBFlowDatabase db = FlowManager.getDatabaseForTable(SimpleModel.class);
        OnTableChangedListener modelChange = (table, action) -> {
            assert action == ChangeAction.INSERT || action == ChangeAction.UPDATE || action == ChangeAction.DELETE;
        };
        DirectModelNotifier.get().registerForTableChanges(SimpleModel.class, modelChange);

        SQLite.insertInto(SimpleModel.class).columnValues(new Pair<>(SimpleModel_Table.name, "name")).executeInsert(db);
        SQLite.update(SimpleModel.class).set(SimpleModel_Table.name.eq("name2")).executeUpdateDelete(db);
        SQLite.delete(SimpleModel.class).executeUpdateDelete(db);
    }

    @After
    public void teardown(){
        FlowManager.destroy();
    }
}
